#include "main.h"
#include "gsm.h"
#include "netpacket.h"
#include "parameters.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include "string.h"
#include "ctype.h"
#include "stdlib.h"

sGSM gsm;
UART_HandleTypeDef USART_InitStructure;

#define GSM_TRASMIT_WHILE_1		0
#define GSM_TRASMIT_FIX			1
#define TIMEOUT_REPLY	100

void GSM_USART_Transmit(char *data, uint8_t type);
void GSM_ClearBuf(void);
eReturn GSM_WhileReply(void);

const char GSM_AT[]				= "AT\r\n";
const char GSM_BAUD[]			= "AT+IPR=3\r\n";
const char GSM_E0[]				= "ATE0\r\n";
const char GSM_RSIIO[]			= "AT+CSQ\r\n";
const char GSM_CFUN1[]			= "AT+CFUN=1\r\n";
const char GSM_CMEE[]			= "AT+CMEE=1\r\n";
const char GSM_GET_CPIN[]		= "AT+CPIN?\r\n";
const char GSM_CPIN_RDY[]		= "+CPIN: READY";
const char GSM_NO_SIM[]			= "+CME ERROR: 10";

const char GSM_CMGF[]			= "AT+CMGF=1\r\n";
const char GSM_CNMI[]			= "AT+CNMI=0\r\n";
const char GSM_CMGL[]			= "AT+CMGL=\"ALL\"\r\n";
const char GSM_CSDH[]			= "AT+CSDH=0\r\n";

const char GSM_CREG[]			= "AT+CREG?\r\n";
const char GSM_CREG0[]			= "AT+CREG=0\r\n";
const char GSM_COPS[]			= "AT+COPS?\r\n";
const char GSM_COPS2[]			= "AT+COPS=2\r\n";
const char GSM_COPS0[]			= "AT+COPS=0\r\n";

const char GSM_CIIXR[]			= "at+CIICR\r\n";

const char GSM_CGATT[]			= "AT+CGATT?\r\n";
const char GSM_GGATT_1[]		= "AT+CGATT=1\r\n";
const char GSM_GET_IP[]			= "AT+CIFSR\r\n";

const char GSM_LINE_END[]		= "\"\r\n";
const char GSM_CRLF[]			= "\r\n";

const char GSM_OK[]				= "OK";
const char GSM_ERROR[]			= "ERROR";
const char GSM_CME_ERROR[]		= "+CME ERROR:";
const char GSM_CMS_ERROR[]		= "+CMS ERROR:";
const char GSM_SHUTDOWN[]		= "SHUTDOWN";
const char GSM_CONNECT[]		= "CONNECT";
const char GSM_NO_CARRIER[]		= "NO CARRIER";

const char GSM_K0[]				= "AT+IFC=0,0\r\n";
const char GSM_PSSTKI[]			= "AT*PSSTKI=0\r\n";
const char GSM_GSN[]			= "AT+GSN\r\n";
const char GSM_CGSN[]			= "AT+CGSN\r\n";

void GSM_copyReply(void)
{
	uint8_t i;
	uint8_t i2=0;
	for(i=0;i<sizeof(gsm.caption.reply);i++)
	{
		if((gsm.commandRx[i] != '\r')&&(gsm.commandRx[i]!='\n'))
		{
			gsm.caption.reply[i2] = gsm.commandRx[i];
			i2++;
		}
	}
	gsm.caption.reply[GSM_COMMAND_CAPRION_BUF-1] = 0;
	gsm.caption.state |= GSM_CAPTION_STATE_UPDATE;
}

void GSM_Task(void *pvParameters)
{
	char str[100];
	uint16_t i;
	uint16_t i2;
	uint8_t i3;
	uint8_t timeout;
	sParamGeneral genPar;
	gsm.state = E_GSM_OK;

	for(;;)
	{
		if(gsm.state == E_GSM_INIT)
		{
			gsm_init_start:
			while(1){
				while(1)
				{
					HAL_GPIO_WritePin(GSM_PWRKEY_PORT, GSM_PWRKEY_PIN, GPIO_PIN_RESET);
					vTaskDelay(2000);
					HAL_GPIO_WritePin(GSM_PWRKEY_PORT, GSM_PWRKEY_PIN, GPIO_PIN_SET);
					vTaskDelay(2000);
					HAL_GPIO_WritePin(GSM_PWRKEY_PORT, GSM_PWRKEY_PIN, GPIO_PIN_RESET);
					vTaskDelay(2000);
					if(HAL_GPIO_ReadPin(GSM_STATUS_PORT, GSM_STATUS_PIN))
						break;

					if(HAL_GPIO_ReadPin(GSM_STATUS_PORT, GSM_STATUS_PIN))
						break;
					if(gsm.state > GSM_MAX_CONFIGURE_ATTEMPTS)
						HAL_NVIC_SystemReset();
				}

				GSM_USART_Transmit((char*)&GSM_AT, GSM_TRASMIT_WHILE_1);
				if(GSM_WhileReply() == E_OK)
				{
					GSM_copyReply();
					break;
				}
			};

			/* Check sim card */
			GSM_USART_Transmit((char*)"AT+CSDT=?\r\n", GSM_TRASMIT_WHILE_1);
			if(GSM_WhileReply()!=E_OK)
				goto gsm_init_start;

			/* Eho off */
			GSM_USART_Transmit((char*)&GSM_E0, GSM_TRASMIT_WHILE_1);
			if(GSM_WhileReply()!=E_OK)
				goto gsm_init_start;
			GSM_copyReply();
			/* Format message */
			GSM_USART_Transmit((char*)GSM_CMGF, GSM_TRASMIT_WHILE_1);
			if(GSM_WhileReply()!=E_OK)
				goto gsm_init_start;
			GSM_copyReply();
			/* End tune */
			gsm.state = E_GSM_OK;
		}

		if(gsm.state == E_GSM_GET_RSSI)
		{
			/* Get value RSSI */
			GSM_USART_Transmit((char*)&GSM_RSIIO, GSM_TRASMIT_WHILE_1);
			GSM_WhileReply();
			GSM_copyReply();
			/* if CSQ reply correct, parsing rssi */
			if((gsm.commandRx[2]=='+')&&(gsm.commandRx[4]=='S')&&(gsm.commandRx[6]==':'))
			{
				memset(&str, 0, sizeof(str));
				i3 = 0;
				for(i2=8;;i2++)
				{
					if(gsm.commandRx[i2]=='\r')
						break;

					if(gsm.commandRx[i2]==',')
						i3++;

					if(i3==0)
					{
						i = strlen((char*)&str);
						str[i++] = gsm.commandRx[i2];
					}
				}
				gsm.caption.rssi = atoi((char*)&str);
				/* calc rssi value % */
				/* 0..31 (-115...-52 dBm)	*/
				if((gsm.caption.rssi!=0)&&(gsm.caption.rssi<=31))
					gsm.caption.rssi = (gsm.caption.rssi * 100)/31;
			}
			gsm.state = E_GSM_OK;
		}

		if(gsm.state == E_GSM_SET_TCP_CONNECT)
		{
			Flash_M25P64_Read_Buffer((uint8_t*)&genPar, ADDRESS_PARAM_GENERAL, sizeof(genPar));
			timeout = 0;
			do
			{
				GSM_USART_Transmit((char*)&GSM_COPS, GSM_TRASMIT_WHILE_1);
				GSM_WhileReply();
				GSM_copyReply();

				GSM_USART_Transmit((char*)"AT+CREG?\r\n", GSM_TRASMIT_WHILE_1);
				GSM_WhileReply();
				GSM_copyReply();

				timeout ++;
				if(timeout > GSM_MAX_CONFIGURE_ATTEMPTS)
				{
					gsm.state = E_GSM_ERR;
					break;
				}
			}while(gsm.commandRx[11] != '1');

			if(gsm.state != E_GSM_ERR)
			{
				GSM_USART_Transmit((char*)"AT+CGATT?\r\n", GSM_TRASMIT_WHILE_1);
				GSM_WhileReply();
				GSM_copyReply();

				strcpy((char*)&str, "AT+CSTT=");
				i = strlen((char*)&str);
				str[i++] = '"';
				i = strlen((char*)&str);
				strcpy((char*)&str[i], (char*)&genPar.gsm_apn);
				i = strlen((char*)&str);
				str[i++] = '"';
				strcpy((char*)&str[i], "\r\n");
				GSM_USART_Transmit((char*)str, GSM_TRASMIT_WHILE_1);
				vTaskDelay(2000);
				GSM_copyReply();

				GSM_USART_Transmit((char*)"AT+CIICR\r\n", GSM_TRASMIT_WHILE_1);
				vTaskDelay(2000);
				GSM_copyReply();

				GSM_USART_Transmit((char*)"AT+CIFSR\r\n", GSM_TRASMIT_WHILE_1);
				vTaskDelay(2000);
				GSM_copyReply();

				/* Set Dest Ip, Port */
				memset(str, 0, sizeof(str));
				strcpy((char*)&str, "AT+CIPSTART=\"TCP\",");
				i=strlen((char*)&str);
				str[i++]='"';
				for(i2=0;i2<4;i2++)
				{
					i3 = strlen((char*)&str);
					sprintf((char*)&str[i3], "%d", startParam.net.ip_dest[i2]);
					if(i2<3)
					{
						i3 = strlen((char*)&str);
						str[i3] = '.';
					}
				}
				i = strlen(str);
				str[i++]='"';
				/* Dest Port */
				str[i++]=',';
				str[i++]='"';
				i = strlen(str);
				sprintf((char*)&str[i], "%d", startParam.net.destPort);
				i = strlen(str);
				str[i++]='"';
				str[i++]=0x0D;
				str[i++]=0x0A;
				GSM_USART_Transmit((char*)str, GSM_TRASMIT_WHILE_1);
				vTaskDelay(2000);
				GSM_copyReply();

				GSM_USART_Transmit((char*)GSM_GET_IP, GSM_TRASMIT_WHILE_1);
				GSM_WhileReply();
				GSM_copyReply();
				if((gsm.commandRx[0]=='\r') && (gsm.commandRx[1]=='\n') && (gsm.commandRx[2]>='0') && (gsm.commandRx[3]<='9'))
				{
					GSM_USART_Transmit((char*)"AT+SAPBR=4,1\r\n", GSM_TRASMIT_WHILE_1);
					GSM_WhileReply();
					GSM_copyReply();
					gsm.state = E_GSM_OK;
				}else
					gsm.state = E_GSM_ERR;
			}else
				gsm.state = E_GSM_ERR;
		}

		if(gsm.state == E_GSM_TCP_SEND)
		{
			i = strlen((char*)&netStruct.netPacket);
			if(i>GSM_MAX_LENG_PACK)
			{
				i2 = 0;
				while(i2<GSM_MAX_LENG_PACK)
				{
					sprintf((char*)&str, "%d", GSM_MAX_LENG_PACK);
					GSM_USART_Transmit((char*)"AT+CIPSEND=", GSM_TRASMIT_WHILE_1);
					GSM_USART_Transmit((char*)str, GSM_TRASMIT_WHILE_1);
					GSM_USART_Transmit((char*)"\r\n", GSM_TRASMIT_WHILE_1);
					GSM_WhileReply();

					GSM_USART_Transmit((char*)netStruct.netPacket, GSM_TRASMIT_FIX);
					memset(str, 0, sizeof(str));
					str[0]=0x0A;
					str[1]='\r';
					str[2]='\n';
					GSM_USART_Transmit((char*)netStruct.netPacket, GSM_TRASMIT_WHILE_1);
					GSM_WhileReply();

					/* Increment Leng */
					i2 += GSM_MAX_LENG_PACK;
				}
				i = strlen((char*)&netStruct.netPacket[i2]);
			}
			strcpy((char*)&str, "AT+CIPSEND=");
			i = strlen((char*)&str);
			i2 = strlen((char*)&netStruct.netPacket);
			sprintf((char*)&str[i], "%d", i2);
			i = strlen((char*)&str);
			strcpy((char*)&str[i], "\r\n");
			GSM_USART_Transmit((char*)str, GSM_TRASMIT_WHILE_1);
			GSM_WhileReply();

			GSM_USART_Transmit((char*)netStruct.netPacket, GSM_TRASMIT_FIX);
			while(gsm.stateTxRx != 0);
			memset(str, 0, sizeof(str));
			strcpy((char*)&str, "\r\n");
			GSM_USART_Transmit((char*)str, GSM_TRASMIT_WHILE_1);
			GSM_WhileReply();

			gsm.state = E_GSM_OK;
		}

		if(gsm.state == E_GSM_SET_TCP_DISCONNECT)
		{
			GSM_USART_Transmit((char*)"AT+CIPCLOSE\r\n", GSM_TRASMIT_WHILE_1);
			GSM_WhileReply();
			GSM_copyReply();

			gsm.state = E_GSM_OK;
		}

		vTaskDelay(500);
	}
}

eReturn GSM_Init(void){
	gsm.state = E_GSM_INIT;
	while((gsm.state != E_GSM_ERR) && (gsm.state != E_GSM_OK))
		vTaskDelay(100);
	return E_OK;
}

eReturn GSM_get_RSSI(void){
	gsm.state = E_GSM_GET_RSSI;
	while((gsm.state != E_GSM_ERR) && (gsm.state != E_GSM_OK))
		vTaskDelay(100);
	return gsm.state;
}

eReturn GSM_set_TCP_connect(void){
	gsm.state = E_GSM_SET_TCP_CONNECT;
	while((gsm.state != E_GSM_ERR) && (gsm.state != E_GSM_OK))
		vTaskDelay(100);
	if(gsm.state == E_GSM_OK)
		return E_OK;
	else
		return E_EROR;
}

eReturn GSM_TCP_send(void){
	gsm.state = E_GSM_TCP_SEND;
	while((gsm.state != E_GSM_ERR) && (gsm.state != E_GSM_OK))
		vTaskDelay(100);
	if(gsm.state == E_GSM_OK)
		return E_OK;
	else
		return E_EROR;
}

eReturn GSM_TCP_disconnect(void){
	gsm.state = E_GSM_SET_TCP_DISCONNECT;
	while((gsm.state != E_GSM_ERR) && (gsm.state != E_GSM_OK))
		vTaskDelay(100);
	if(gsm.state == E_GSM_OK)
		return E_OK;
	else
		return E_EROR;
}


void GSM_USART_IRQHandler(void)
{
	if(GSM_USART->SR & USART_SR_RXNE)
	{
		if(gsm.commandRxLeng < (sizeof(gsm.commandRx)))
			gsm.commandRx[gsm.commandRxLeng++] = GSM_USART->DR;
	}
	GSM_USART->SR = 0;
}

void GSM_USART_Transmit(char *data, uint8_t type)
{
	GSM_ClearBuf();
	if(type == GSM_TRASMIT_FIX)
		data = (char*)&netStruct.netPacket;

	while(*data)
	{
		while(__HAL_USART_GET_FLAG(&USART_InitStructure, USART_FLAG_TXE) == RESET);
		GSM_USART->DR = *data;
		(data)++;
	}
}

void GSM_ClearBuf(void)
{
	memset(&gsm.commandTx, 0, sizeof(gsm.commandTx));
	memset(&gsm.commandRx, 0, sizeof(gsm.commandRx));
	gsm.commandTxLeng = 0;
	gsm.commandRxLeng = 0;
	gsm.state = 0;
	gsm.stateTxRx = 0;
}

eReturn GSM_WhileReply(void)
{
	uint8_t i;
	uint8_t timeout=0;
	while(timeout<TIMEOUT_REPLY)
	{
		for(i=0;i<(GSM_COMMNAD_BUF-1); i++)
		{
			if((gsm.commandRx[i]=='\r') && (gsm.commandRx[i+1]=='\n'))
			{
				vTaskDelay(1000);
				return E_OK;
			}
		}
		vTaskDelay(10);
		timeout ++;
	};
	return E_EROR;
}

void GSM_periph_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/* Set clock */
	RCC->AHB1ENR |= GSM_GPIO_RCC;
	/* Inits Ports */
	/* RXD */
	GPIO_InitStruct.Pin =  GSM_RXD_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Alternate = GSM_GPIO_AF;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_RXD_PORT, &GPIO_InitStruct);
	/* TXD */
	GPIO_InitStruct.Pin =  GSM_TXD_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Alternate = GSM_GPIO_AF;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_TXD_PORT, &GPIO_InitStruct);
	/* PWR */
	GPIO_InitStruct.Alternate = 0;
	GPIO_InitStruct.Pin =  GSM_PWRKEY_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_PWRKEY_PORT, &GPIO_InitStruct);
	/* RESET */
	GPIO_InitStruct.Pin =  GSM_RESET_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_RESET_PORT, &GPIO_InitStruct);
	/* Status */
	GPIO_InitStruct.Pin =  GSM_STATUS_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_STATUS_PORT, &GPIO_InitStruct);
	/* SIM presence  */
	GPIO_InitStruct.Pin =  GSM_PRESENC_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
	HAL_GPIO_Init(GSM_PRESENC_PORT, &GPIO_InitStruct);
	GSM_PRESENC_PORT->ODR &=~ GSM_PRESENC_PIN;
	/* Enabled clock USART */
	GSM_USARTx_CLK_ENABLE();
	USART_InitStructure.Instance = GSM_USART;
	USART_InitStructure.Init.BaudRate	= GSM_USART_BAUDRATE;
	USART_InitStructure.Init.WordLength	= UART_WORDLENGTH_8B;
	USART_InitStructure.Init.StopBits	= UART_STOPBITS_1;
	USART_InitStructure.Init.Parity		= UART_PARITY_NONE;
	USART_InitStructure.Init.HwFlowCtl	= UART_HWCONTROL_NONE;
	USART_InitStructure.Init.Mode		= UART_MODE_TX_RX;
	USART_InitStructure.Init.OverSampling = UART_OVERSAMPLING_16;
	HAL_UART_Init(&USART_InitStructure);
	//__HAL_UART_ENABLE_IT(&USART_InitStructure, UART_IT_TC);
	__HAL_UART_ENABLE_IT(&USART_InitStructure, UART_IT_RXNE);
	/* NVIC configuration for USART TC interrupt */
	HAL_NVIC_SetPriority(GSM_USART_IRQn, 12, 0);
	HAL_NVIC_EnableIRQ(GSM_USART_IRQn);
}
